﻿namespace Refract.UI.Docking
{
    using System;
    using System.Net;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Documents;
    using System.Windows.Ink;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Animation;
    using System.Windows.Shapes;

    using Artefact.Animation;

    using Refract.Event;

    [TemplatePart(Name = "Core", Type = typeof(FrameworkElement))]
    [TemplateVisualState(Name = "Maxmized", GroupName = "CommonStates")]
    [TemplateVisualState(Name = "Minimized", GroupName = "CommonStates")]
    [TemplateVisualState(Name = "Restored", GroupName = "CommonStates")]
    [TemplateVisualState(Name = "Closed", GroupName = "CommonStates")]
    public class DockableElement : Control, IDockable
    {
        #region Fields

        private double _originalElementWidth, _originalElementHeight;

        #endregion Fields

        #region Constructors

        public DockableElement()
        {
            DefaultStyleKey = typeof(DockableElement);

            DragService = new DragService();
            DragService.Attach(this);

            DockableService = new DockableService();
            DockableService.Attach(this);
        }

        #endregion Constructors

        #region Properties

        public FrameworkElement Core
        {
            get; set;
        }

        public DockableService DockableService
        {
            get; set;
        }

        public DragService DragService
        {
            get; set;
        }

        public DockableState State
        {
            get; private set;
        }

        #endregion Properties

        #region Methods

        public void Close(SimpleCallback callback = null)
        {
            State = DockableState.Closed;
            GotoState();
        }

        public void Maximize(SimpleCallback callback = null)
        {
            FrameworkElement container = Parent as FrameworkElement;

            ArtefactAnimator.AddEase(this, new[] { Canvas.LeftProperty, Canvas.TopProperty }, new[] { 0, 0 }, .2,
                         AnimationTransitions.PowerEaseInOut, 0);
            ArtefactAnimator.AddEase(this, new[] { FrameworkElement.WidthProperty, FrameworkElement.HeightProperty },
                new[] { container.ActualWidth, container.ActualHeight }, .2, AnimationTransitions.PowerEaseInOut, 0);

            State = DockableState.Maximized;

            GotoState();
        }

        public void Minimize(SimpleCallback callback = null)
        {
            State = DockableState.Minimized;
            GotoState();
        }

        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
            _originalElementWidth = Width;
            _originalElementHeight = Height;

            Core = (Panel)GetTemplateChild("Core");
            GotoState();
        }

        public void Restore(SimpleCallback callback = null)
        {
            ArtefactAnimator.AddEase(this, new[] { FrameworkElement.WidthProperty, FrameworkElement.HeightProperty },
            new[] { _originalElementWidth, _originalElementHeight }, .1, AnimationTransitions.PowerEaseInOut, 0);
            State = DockableState.Restored;

            DockableService.GripOffsetX = _originalElementWidth / 2;
            DockableService.GripOffsetY = _originalElementHeight / 2;

            GotoState();
        }

        private void GotoState(bool useTransitions = true)
        {
            VisualStateManager.GoToState(this, State.ToString(), useTransitions);
        }

        #endregion Methods
    }
}